package com.funsport.service.impl;

import com.funsport.entity.*;
import com.funsport.service.*;
import com.funsport.service.IPointsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * 积分服务实现
 * 处理用户积分、俱乐部积分的增减和管理
 *
 * @author Fun-Sport Team
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PointsServiceImpl implements IPointsService {

    private final IUserService userService;
    private final IClubService clubService;
    @Lazy
    private final IClubMemberService clubMemberService;
    private final IPointRecordService pointRecordService;
    private final IClubPointRecordService clubPointRecordService;
    private final IEventService eventService;
    @Lazy
    private final ICommunityPostService communityPostService;

    // 积分规则配置
    private static final Map<String, Integer> POINTS_RULES = new HashMap<String, Integer>() {{
        // 活动相关积分规则已调整：
        // - 取消报名活动积分（原10分）
        // - 参加活动基础积分改为15分，超2小时为20分（在awardEventPoints方法中动态计算）
        put("attend_event", 15);      // 参加活动（基础积分，超2小时为20分）
        put("create_event", 30);      // 创建活动
        put("join_club", 15);         // 加入俱乐部
        put("create_club", 50);       // 创建俱乐部
        put("daily_checkin", 5);      // 每日签到
        put("share_event", 5);        // 分享活动
        put("invite_friend", 20);     // 邀请好友
        put("complete_profile", 10);  // 完善资料
        
        // 帖子相关积分
        put("first_post", 10);        // 第一次发布帖子
        put("post_like", 3);          // 帖子被点赞
        put("post_favorite", 3);      // 帖子被收藏
        put("post_comment", 3);       // 帖子被回复
    }};

    // 等级配置
    private static final int[][] LEVEL_CONFIG = {
            {1, 0, 99},           // 等级1: 新手
            {2, 100, 299},        // 等级2: 进阶
            {3, 300, 599},        // 等级3: 熟练
            {4, 600, 999},        // 等级4: 专业
            {5, 1000, 1999},      // 等级5: 大师
            {6, 2000, 999999}     // 等级6: 传奇
    };

    private static final String[] LEVEL_NAMES = {"", "新手", "进阶", "熟练", "专业", "大师", "传奇"};

    @Override
    @Transactional
    public boolean addUserPoints(Long userId, Integer points, String reason, String relatedType, Long relatedId) {
        User user = userService.getById(userId);
        if (user == null) {
            log.warn("用户不存在: userId={}", userId);
            return false;
        }

        // 增加积分
        user.setPoints(user.getPoints() + points);

        // 更新等级
        int newLevel = calculateLevel(user.getPoints());
        user.setLevel(newLevel);

        // 保存用户
        userService.updateById(user);

        // 记录积分变更
        PointRecord record = new PointRecord();
        record.setUserId(userId);
        record.setPointsChange(points);
        record.setPointType(getPointTypeByReason(reason));
        record.setReason(reason);
        record.setDescription(reason);
        if ("event".equals(relatedType)) {
            record.setRelatedEventId(relatedId);
        } else if ("club".equals(relatedType)) {
            record.setRelatedClubId(relatedId);
        }
        pointRecordService.save(record);

        log.info("用户积分增加成功: userId={}, points={}, newTotal={}, newLevel={}", 
                userId, points, user.getPoints(), newLevel);
        return true;
    }

    @Override
    @Transactional
    public boolean deductUserPoints(Long userId, Integer points, String reason) {
        User user = userService.getById(userId);
        if (user == null) {
            log.warn("用户不存在: userId={}", userId);
            return false;
        }

        // 检查积分是否足够
        if (user.getPoints() < points) {
            log.warn("用户积分不足: userId={}, currentPoints={}, needPoints={}", 
                    userId, user.getPoints(), points);
            return false;
        }

        // 扣除积分
        user.setPoints(user.getPoints() - points);

        // 更新等级
        int newLevel = calculateLevel(user.getPoints());
        user.setLevel(newLevel);

        // 保存用户
        userService.updateById(user);

        // 记录积分变更
        PointRecord record = new PointRecord();
        record.setUserId(userId);
        record.setPointsChange(-points);
        record.setPointType(getPointTypeByReason(reason));
        record.setReason(reason);
        record.setDescription(reason);
        pointRecordService.save(record);

        log.info("用户积分扣除成功: userId={}, points={}, newTotal={}", userId, points, user.getPoints());
        return true;
    }

    @Override
    @Transactional
    public boolean addClubPoints(Long clubId, Integer points, Long userId, String reason) {
        Club club = clubService.getById(clubId);
        if (club == null) {
            log.warn("俱乐部不存在: clubId={}", clubId);
            return false;
        }

        // 增加俱乐部积分
        club.setPoints(club.getPoints() + points);

        // 更新俱乐部等级
        int newLevel = calculateClubLevel(club.getPoints());
        club.setLevel(newLevel);

        // 保存俱乐部
        clubService.updateById(club);

        // 记录积分变更
        ClubPointRecord record = new ClubPointRecord();
        record.setClubId(clubId);
        record.setPointsChange(points);
        record.setReason(reason);
        record.setDescription(reason);
        record.setRelatedUserId(userId);
        clubPointRecordService.save(record);

        log.info("俱乐部积分增加成功: clubId={}, points={}, userId={}, newTotal={}", 
                clubId, points, userId, club.getPoints());
        return true;
    }

    /**
     * 根据原因获取积分类型
     */
    private String getPointTypeByReason(String reason) {
        if (reason == null) {
            return "other";
        }
        
        // 根据原因映射到数据库枚举值
        if (reason.contains("签到") || reason.contains("checkin")) {
            return "signin";
        } else if (reason.contains("加入") || reason.contains("join")) {
            return "event_join";
        } else if (reason.contains("完成") || reason.contains("complete")) {
            return "event_complete";
        } else if (reason.contains("邀请") || reason.contains("invite")) {
            return "invite";
        } else if (reason.contains("评价") || reason.contains("review")) {
            return "review";
        } else if (reason.contains("发帖") || reason.contains("post")) {
            return "post";
        } else {
            return "other";
        }
    }

    @Override
    public int calculateLevel(Integer points) {
        if (points == null || points < 0) {
            return 1;
        }

        for (int[] config : LEVEL_CONFIG) {
            int level = config[0];
            int minPoints = config[1];
            int maxPoints = config[2];
            if (points >= minPoints && points <= maxPoints) {
                return level;
            }
        }
        return 1;
    }

    @Override
    public int calculateClubLevel(Integer points) {
        if (points == null || points < 0) {
            return 1;
        }

        // 俱乐部等级规则（更高要求）
        if (points >= 6000) return 5;
        if (points >= 3000) return 4;
        if (points >= 1500) return 3;
        if (points >= 500) return 2;
        return 1;
    }

    @Override
    public Map<String, Object> getUserLevelInfo(Integer points) {
        Map<String, Object> info = new HashMap<>();

        int currentLevel = calculateLevel(points);
        info.put("currentLevel", currentLevel);
        info.put("currentLevelName", LEVEL_NAMES[currentLevel]);
        info.put("currentPoints", points);

        // 查找下一等级
        Integer nextLevel = null;
        String nextLevelName = null;
        Integer pointsToNext = 0;
        Double progress = 100.0;

        for (int i = 0; i < LEVEL_CONFIG.length; i++) {
            if (LEVEL_CONFIG[i][0] == currentLevel && i + 1 < LEVEL_CONFIG.length) {
                nextLevel = LEVEL_CONFIG[i + 1][0];
                nextLevelName = LEVEL_NAMES[nextLevel];
                int nextLevelMinPoints = LEVEL_CONFIG[i + 1][1];
                pointsToNext = nextLevelMinPoints - points;

                // 计算升级进度
                int currentLevelMin = LEVEL_CONFIG[i][1];
                progress = ((double) (points - currentLevelMin) / 
                           (nextLevelMinPoints - currentLevelMin)) * 100;
                break;
            }
        }

        info.put("nextLevel", nextLevel);
        info.put("nextLevelName", nextLevelName);
        info.put("pointsToNext", pointsToNext);
        info.put("progress", Math.round(progress * 10.0) / 10.0);

        return info;
    }

    @Override
    public boolean awardEventPoints(Long userId, Long eventId, String action) {
        // 报名活动不再奖励积分
        if ("signup".equals(action)) {
            log.info("报名活动不再奖励积分: userId={}, eventId={}", userId, eventId);
            return true;
        }
        
        Integer points = POINTS_RULES.get(action + "_event");
        if (points == null || points <= 0) {
            log.warn("无效的活动动作: action={}", action);
            return false;
        }

        // 如果是参加活动（签到），根据活动时长调整积分
        if ("attend".equals(action)) {
            Event event = eventService.getById(eventId);
            if (event != null && event.getStartTime() != null && event.getEndTime() != null) {
                long hours = java.time.Duration.between(event.getStartTime(), event.getEndTime()).toHours();
                if (hours >= 2) {
                    points = 20;  // 活动超2小时，奖励20分
                    log.info("活动超2小时，奖励20分: eventId={}, hours={}", eventId, hours);
                } else {
                    points = 15;  // 普通活动，奖励15分
                    log.info("普通活动，奖励15分: eventId={}, hours={}", eventId, hours);
                }
            }
        }

        return addUserPoints(userId, points, "活动" + action, "event", eventId);
    }

    @Override
    public boolean awardClubPoints(Long userId, Long clubId, String action) {
        Integer points = POINTS_RULES.get(action + "_club");
        if (points == null || points <= 0) {
            log.warn("无效的俱乐部动作: action={}", action);
            return false;
        }

        return addUserPoints(userId, points, "俱乐部" + action, "club", clubId);
    }
}

